package com.lifang.framework.beans.factory.support;

import cn.hutool.core.util.StrUtil;
import com.lifang.framework.beans.factory.DisposableBean;
import com.lifang.framework.beans.BeansException;

import java.lang.reflect.Method;

/**
 * bean销毁 适配器
 */
public class DisposableBeanAdapter implements DisposableBean {

    /**
     * bean对象
     */
    private final Object bean;

    /**
     * bean名称
     */
    private final String beanName;

    /**
     * 销毁方法
     */
    private final String destroyMethodName;

    private Method destroyMethod;

    public DisposableBeanAdapter(Object bean, String beanName, BeanDefinition beanDefinition) {
        this.bean = bean;
        this.beanName = beanName;
        this.destroyMethodName = beanDefinition.getDestroyMethodName();
        if (StrUtil.isNotBlank(this.destroyMethodName)) {
            for (Method method : beanDefinition.getBeanClass().getMethods()) {
                if (method.getName().equals(this.destroyMethodName)) {
                    if (method.getParameterCount() > 0) {
                        throw new BeansException(beanName + " destroy method not allow method input parameter");
                    }
                    this.destroyMethod = method;
                    break;
                }
            }
            if (destroyMethod == null) {
                throw new BeansException("bean " + beanName + " no named " + destroyMethodName + " method," + " maybe method not public");
            }
        }
    }

    @Override
    public void destroy() throws Exception {
        // 1. 实现接口 DisposableBean
        if (bean instanceof DisposableBean) {
            ((DisposableBean) bean).destroy();
        }

        // 2. 注解配置 destroy-method 判断是为了避免二次执行销毁
        if (StrUtil.isNotEmpty(destroyMethodName) && this.destroyMethod != null) {
            try {
                this.destroyMethod.invoke(bean);
            } catch (Exception ex) {
                throw new BeansException("bean " + beanName + " destroy method implement exception", ex);
            }
        }
    }

}
